import {getJudgeProblemResult, getTestJudgeResult, submitProblemJudge, submitTest} from "@/api/judge";
import type {RunResult,JudgeResult,SubmitJudgeDTO,TestJudgeDTO} from  "@/api/judge";
import {getTypeByStatus} from "@/common/enum";
import type {JudgeType} from "@/common/enum";


export interface IJudge{
    runResult : RunResult
    judgeResults: Array<JudgeResult>
    submitProblemTest : (data : TestJudgeDTO) => void;
    submitJudgeProblem: (data : SubmitJudgeDTO) => Promise<JudgeResult>;
    getRunResult : () => RunResult;
    testProcess: () => boolean;
}
export class Judge implements IJudge{

    private runResult : RunResult
    private judgeResults: Array<JudgeResult>;
    private interval : number;

    constructor(testStatus : RunResult,judgeResults : Array<JudgeResult>) {
        this.runResult = testStatus;
        this.judgeResults =  judgeResults;
    }

    /**
     * 提交测试用例
     * @param data
     */
    public async submitProblemTest(data: TestJudgeDTO) {

        if(this.testProcess()){
            return;
        }
        this.updateStatus({status : 9,msg:'',file:''}) //标识提交中
        const key = await submitTest(data)
        this.interval = setInterval(async () => {
            try {
                const res = await getTestJudgeResult({testJudgeKey: key.data})
                this.updateStatus(res.data);
                if(!this.testProcess()){
                    clearInterval(this.interval);
                }
            } catch (e) {
                console.error(e)
                clearInterval(this.interval);
                this.updateStatus({
                    status:4
                })
            }
        }, 2000);
    }


    /**
     * 根据运行结果更新状态
     * @param runResult
     * @private
     */
    private updateStatus(runResult : RunResult):void{
        Object.assign(this.runResult, runResult);
    }


    /**
     * 测试数据是否在流程中
     */
    public testProcess = () : boolean => {
        const status = this.runResult.status;
        return this.iSInProcess(status)
    }

    /**
     * 是否在流程中
     */
    public iSInProcess = (status) : boolean => {
        return status == '5' || status == '6' || status == '7' || status == '9'
    }


    /**
     * 判题总入口
     * @param data
     */
    public async submitJudgeProblem(data: SubmitJudgeDTO): Promise<JudgeResult> {
        const t = await submitProblemJudge(data)
        let interval = null;
        const judgeResult = t.data;
        this.judgeResults.unshift(judgeResult);
        interval = setInterval(async () => {
            try {
                const res = await getJudgeProblemResult({judgeId: t.data.id})
                Object.assign(judgeResult, res.data);
                if(!this.iSInProcess(res.data.status)){
                    clearInterval(interval);
                }
            } catch (e) {
                console.error(e)
                clearInterval(interval);
                judgeResult.status = 4;
            }
        }, 2000);

        return judgeResult;
    }

    getRunResult(): RunResult {
        return this.runResult;
    }

}


const languagesMap = {
    'cpp':'C++'
}

export const JUDGE_STATUS  = {
    '-10': {
        title: 'Not Submitted',
        short: 'NS',
        color: 'gray',
        type: 'info',
        rgb:'#909399'
    },
    '-5': {
        name: 'Submitted Unknown Result',
        short: 'SNR',
        color: 'gray',
        type: 'info',
        rgb:'#909399'
    },
    '-4': {
        name: 'Cancelled',
        short: 'CA',
        color: 'purple',
        type: 'info',
        rgb:'#676fc1'
    },
    '-3': {
        name: 'Presentation Error',
        short: 'PE',
        color: 'yellow',
        type: 'warning',
        rgb:'#f90'
    },
    '-2': {
        name: 'Compile Error',
        short: 'CE',
        color: 'yellow',
        type: 'warning',
        rgb:'#f90'
    },
    '-1': {
        name: 'Wrong Answer',
        short: 'WA',
        color: 'red',
        type: 'error',
        rgb:'#ed3f14'
    },
    '0': {
        name: 'Accepted',
        short: 'AC',
        color: 'green',
        type: 'success',
        rgb:'#19be6b'
    },
    '1': {
        name: 'Time Limit Exceeded',
        short: 'TLE',
        color: 'red',
        type: 'error',
        rgb:'#ed3f14'
    },
    '2': {
        name: 'Memory Limit Exceeded',
        short: 'MLE',
        color: 'red',
        type: 'error',
        rgb:'#ed3f14'
    },
    '3': {
        name: 'Runtime Error',
        short: 'RE',
        color: 'red',
        type: 'error',
        rgb:'#ed3f14'
    },
    '4': {
        name: 'System Error',
        short: 'SE',
        color: 'gray',
        type: 'info',
        rgb:'#909399'
    },
    '5': {
        name: 'Pending',
        color: 'yellow',
        type: 'warning',
        rgb:'#f90'
    },
    '6':{
        name: 'Compiling',
        short: 'CP',
        color: 'green',
        type: 'info',
        rgb:'#25bb9b'
    },
    '7': {
        name: 'Judging',
        color: 'blue',
        type: '',
        rgb:'#2d8cf0'
    },
    '8': {
        name: 'Partial Accepted',
        short: 'PAC',
        color: 'blue',
        type: '',
        rgb:'#2d8cf0'
    },
    '9': {
        name: 'Submitting',
        color: 'yellow',
        type: 'warning',
        rgb:'#f90'
    },
    '10':{
        name:"Submitted Failed",
        color:'gray',
        short:'SF',
        type: 'info',
        rgb:'#909399',
    }
}


export default languagesMap
